import 'dart:async';
import 'dart:math' as math;
import 'package:FineArt/core/api/course_api.dart';
import 'package:FineArt/utils/image_utils.dart';
import 'package:FineArt/utils/log_util.dart';
import 'package:FineArt/utils/platform_util.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:orientation/orientation.dart';
import 'package:photo_view/photo_view.dart';

class CourseView extends StatefulWidget {
  String url;
  int courseid;

  CourseView({this.url, this.courseid});

  static Jump2CourseView(String url, int courseid, context) {
    Navigator.of(context).push(MaterialPageRoute(builder: (context) {
      return CourseView(
        url: url,
        courseid: courseid,
      );
    }));
  }

  @override
  _CourseViewState createState() => _CourseViewState();
}

class _CourseViewState extends State<CourseView> {
  final PhotoViewController _controller = PhotoViewController();
  var _quarterTurns = 0;
  DeviceOrientation _currentOrientation;

  double _scale_step = 0.5;
  double _initScale = -1.0;
  double _currentScale;
  Offset _currentOffset;
  double _maxScale = 1;
  dynamic _minScale;

  int imageW;
  int imageH;
  double canvasW;
  double canvasH;

  Rect imageRect;

  @override
  void dispose() {
    _controller.dispose();
    CourseApi().delete();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();

    OrientationPlugin.setPreferredOrientations(DeviceOrientation.values);
    OrientationPlugin.setEnabledSystemUIOverlays(SystemUiOverlay.values);

    OrientationPlugin.onOrientationChange.listen((orientation) {
      // If the widget was removed from the tree while the asynchronous platform
      // message was in flight, we want to discard the reply rather than calling
      // setState to update our non-existent appearance.

      if (_currentOrientation.toString() == orientation.toString()) return;

      _currentOrientation = orientation;

      LogUtil.d("==>orientation changed1:" + orientation.toString());

      if (!mounted) return;
      OrientationPlugin.forceOrientation(orientation).then((value) {
        _initScale = -1;
        setState(() {
          _minScale = PhotoViewComputedScale.contained;
        });
      });
    });
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    new Future.delayed(Duration(milliseconds: 500), () {
      _controller.reset();
      LogUtil.d("==>initial position:(" +
          _controller.position.dx.toString() +
          "," +
          _controller.position.dy.toString() +
          ")");

      LogUtil.d("==>initial scale:" + _controller.scale.toString());
      LogUtil.d("==>initial imageH:" + (imageH * _controller.scale).toString());
    });
  }

  void _sendOperation(String oper, String value) {
    SimpleOperation operation = new SimpleOperation(oper: oper, value: value);
    CourseApi(dio: PlatformUtil.getDio()).operate(widget.courseid, operation);
  }

  void _doMove(DragUpdateDetails e) {
    Offset o = _controller.position;
    Offset new_off = Offset(o.dx + e.delta.dx, o.dy + e.delta.dy);
    _controller.position = new_off;
  }

  void _doScale() {
    if (_initScale == -1.0) {
      _initScale = _controller.scale;
    }

    if (_controller.scale == _maxScale) {
      _controller.scale = _initScale;
      return;
    }

    if (_controller.scale + _scale_step >= _maxScale) {
      _controller.scale = _maxScale;
      return;
    }

    _controller.scale += _scale_step;
  }

  void _doScaleAndMove(ScaleUpdateDetails e) {
    Offset offset = e.focalPoint - _currentOffset;

    if (offset.dx.abs() > 1.0 || offset.dy.abs() > 1.0) {
      double _dx = offset.dx;
      double _dy = offset.dy;
      Offset o = _controller.position;
      Offset new_off = Offset(o.dx + _dx, o.dy + _dy);
      _controller.position = new_off;
      _currentOffset = e.focalPoint;
    }

    _controller.scale = _currentScale * e.scale;
    if (_controller.scale >= _maxScale) {
      _controller.scale = _maxScale;
      return;
    }
    if (_controller.scale <= _initScale) {
      _controller.scale = _initScale;
      return;
    }
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    canvasW = size.width;
    canvasH = size.height;
    if (size.height > size.width) {
      canvasH = size.width * 1080 / 1920;
    } else {
      canvasW = size.height * 1920 / 1080;
    }

    Image image = new Image(
      image: CachedNetworkImageProvider(widget.url),
    );

    image.image.resolve(ImageConfiguration()).addListener(
      ImageStreamListener(
        (info, call) {
          imageW = info.image.width;
          imageH = info.image.height;
        },
      ),
    );

    return Scaffold(
      backgroundColor: Colors.black,
      body: Center(
        child: Container(
          height: canvasH,
          width: canvasW,
          color: Colors.red,
          child: GestureDetector(
            // onHorizontalDragEnd: (d) => {LogUtil.d("==>on drag1")},
            // onVerticalDragEnd: (d) => {LogUtil.d("==>on drag2")},
            // onPanUpdate: (e) => {_doMove(e)},
            // onDoubleTap: () => {_doScale()},
            onScaleEnd: (e) {
              double ratio = MediaQuery.of(context).devicePixelRatio;
              new Future.delayed(Duration(milliseconds: 5), () {
                LogUtil.d("\n==>----------------");
                LogUtil.d("==>position:" + _controller.position.toString());
                LogUtil.d("==>position.dx:" + _controller.position.dx.toString());
                LogUtil.d("==>scale:" + _controller.scale.toString());
                double iw = imageW * _controller.scale;
                double ih = imageH * _controller.scale;
                LogUtil.d("==>iw:" + iw.toString());
                LogUtil.d("==>ih:" + ih.toString());
                LogUtil.d("==>canvasW:" + canvasW.toString());
                LogUtil.d("==>canvasH:" + canvasH.toString());
                LogUtil.d("==>ratio:" + ratio.toString());
                double left = _controller.position.dx + canvasW / 2 - iw / 2;
                LogUtil.d("==>left:" + left.toString());
                double top = _controller.position.dy + canvasH / 2 - ih / 2;
                LogUtil.d("==>top:" + top.toString());
                LogUtil.d("==>----------------\n");
              });},
            onScaleUpdate: (e) => {_doScaleAndMove(e)},
            onScaleStart: (e) {
              if (_initScale == -1.0) {
                _initScale = _controller.scale;
              }
              _currentScale = _controller.scale;
              _currentOffset = e.focalPoint;
            },
            child: ClipRect(
              child: PhotoView(
                controller: _controller,
                imageProvider: image.image,
                maxScale: _maxScale,
                initialScale: _minScale,
                minScale: _minScale,
                enableRotation: false,
                disableGestures: true,
                basePosition: Alignment.center,
                loadingBuilder: (context, event) => Center(
                  child: Container(
                    width: 30.0,
                    height: 30.0,
                    child: CircularProgressIndicator(
                      value: event == null
                          ? 0
                          : event.cumulativeBytesLoaded /
                              event.expectedTotalBytes,
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
      // floatingActionButton: FloatingActionButton(
      //   child: Text("旋转"),//const Icon(Icons.rotate_right),
      //   onPressed: _rotateRight90Degrees,
      // ),
    );
  }

  void _rotateRight90Degrees() {
    // Set the rotation to either 0, 90, 180 or 270 degrees (value is in radians)
    _quarterTurns = _quarterTurns == 3 ? 0 : _quarterTurns + 1;
    _controller.rotation = math.pi / 2 * _quarterTurns;
  }
}
